home *** CD-ROM | disk | FTP | other *** search
- /*
- Exponential Fit
- */
-
- #include <stdio.h>
- #include <spec.h>
-
- float *spc, *err, *tim, *usp1, *usp2, *uer1, *uer2;
- int flg_v;
- int bgrnd,xbeg,xend;
- float chisq,fit_a, fit_b;
-
- help()
- {
- printf("\n\nExponential Fit y = c + b * exp(a * x)\n");
- printf("ExpFit file [-o file] [-ba n] [-xbeg n] [-xend n] [-last n]\n");
- printf("options:\n");
- printf(" file spectrum to be fitted\n");
- printf(" -o file output spectrum instead of stdout\n");
- printf(" -ba n background for spectrum (to avoid Background fit)\n");
- printf(" -xbeg n first channel to fit\n");
- printf(" -xend n last channel to fit\n");
- printf(" -last n takes arithmetic mean of last n channels as\n");
- printf(" background. Default is, to find the background\n");
- printf(" by fitting an exponential curve to the spectrum\n");
- printf(" -v verbose mode. Prints fitted parameters\n");
- printf(" -vv very verbose mode. Also Prints fitting progress\n");
- printf("\n(C) Rainer Kowallik\n");
- exit(0);
- }
-
- /* ---------------------------------------------------------
- Liner regression after logarithm of spectrum
- This is only to calculate the chi**2, all
- other values are lost.
- UP TO NOW, THE ERRORBARS ARE NOT INCLUDED !
- I HAVE FORGOTTEN MY OLD SUPERBASIC SOURCE AT HOME, SORRY.
- --------------------------------------------------------- */
-
- float linreg(spc,tim,err,n,a,z)
- float spc[],tim[],err[];
- int n,a,z;
- {
- int i,m,k;
- float ysoll,x,y,sumx,sumxx,sumy,sumyy,sumxy,nges,
- steigung,offset,erg,
- *ylog;
-
- ylog=(float *)calloc(_MAXSPCLEN+2,sizeof(float));
-
- nges = (float) (z-a); /* Number of Elements */
- sumx = 0.0;
- sumxx = 0.0;
- sumy = 0.0;
- sumyy = 0.0;
- sumxy = 0.0;
-
- for(i=a;i<z;i++) {
- x = tim[i];
- y = spc[i];
- y = y - ((float) n);
- if(y<0.1) y=1.0; /* trap overflow on log */
- y = (float) log((double) y); /* linearization of exp function */
- ylog[i] = y; /* store for later use */
- sumx = sumx + x;
- sumxx = sumxx + (x*x);
- sumy = sumy + y;
- sumyy = sumyy + (y*y);
- sumxy = sumxy + (x*y);
- }
- sumx = sumx / nges;
- sumy = sumy / nges;
- sumxx = sumxx - (nges * sumx * sumx);
- sumxy = sumxy - (nges * sumx * sumy);
- sumyy = sumyy - (nges * sumy * sumy);
- steigung = sumxy / sumxx;
- offset = sumy - (steigung * sumx);
-
- /* calculating chi**2 */
-
- erg=0.0;
- for(i=a;i<z;i++) {
- x = tim[i];
- y = ylog[i];
- ysoll = (steigung * x) + offset;
- y = y - ysoll;
- erg = erg + (y * y);
- }
-
- fit_a = steigung;
- fit_b = offset;
-
- free(ylog);
- return(erg);
- }
-
- float sd(x,y)
- float x,y;
- {
- if(y!=0.0) return(x/y);
- return(0.0);
- }
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- int n,m,i,max,flg_ba,lastn;
- char z[80],comment[80],nam[80];
- float x,alpha,sum1,sum2;
- FILE *fp;
-
- flg_ba=0; /* defaults to exponential fit */
- bgrnd = -1;
- flg_v=FALSE;
- xbeg = 0;
- xend = -1;
-
- if(argc < 2) {help(); exit(0);}
- strcpy(nam,argv[1]);
- if(checkopt(argc,argv,"-ba",z)) {
- bgrnd=atoi(z); flg_ba=1;
- }
- if(checkopt(argc,argv,"-xbeg",z)) {
- xbeg = atoi(z);
- }
- if(checkopt(argc,argv,"-xend",z)) {
- xend = atoi(z);
- }
- if(checkopt(argc,argv,"-last",z)) {
- flg_ba=2; lastn = atoi(z);
- }
- if(checkopt(argc,argv,"-v",z)) flg_v=1;
- if(checkopt(argc,argv,"-vv",z)) flg_v=2;
-
- spc=(float *)calloc(_MAXSPCLEN+2,sizeof(float));
- err=(float *)calloc(_MAXSPCLEN+2,sizeof(float));
- tim=(float *)calloc(_MAXSPCLEN+2,sizeof(float));
- usp1=(float *)calloc(_MAXSPCLEN+2,sizeof(float));
- usp2=(float *)calloc(_MAXSPCLEN+2,sizeof(float));
- uer1=(float *)calloc(_MAXSPCLEN+2,sizeof(float));
- uer2=(float *)calloc(_MAXSPCLEN+2,sizeof(float));
-
- /* -----------------------------------------------
- reading spectrum
- ----------------------------------------------- */
-
- max=readspec(nam,usp1,uer1,tim,comment);
- if(xend < 0) xend = max - 1;
-
- /* -----------------------------------------------
- generating error spectrum
- ----------------------------------------------- */
- for(n=0;n<max;n++) {
- uer1[n] = sqrt(usp1[n]);
- }
-
- /* --------------------------------------------
- finding correct background
- -------------------------------------------- */
-
- switch(flg_ba) {
- case 0:
- bgrnd = expbafit(usp1,tim,uer1,xbeg,xend);
- chisq = linreg(usp1,tim,uer1,bgrnd,xbeg,xend);
- break;
- case 1: /* allready done when parsing arguments */
- chisq = linreg(usp1,tim,uer1,bgrnd,xbeg,xend);
- break;
- case 2:
- bgrnd = sumspc(usp1,max-lastn,max) / lastn;
- chisq = linreg(usp1,tim,uer1,bgrnd,xbeg,xend);
- break;
- }
-
- fit_b = exp(fit_b);
-
- if(flg_v) {
- printf("CHI**2 = %f\n",chisq);
- printf("background = %d\n",bgrnd);
- printf("b (t0) = %f\n",fit_b);
- printf("a (Tau) = %f\n",-1.0/fit_a);
- }
-
- /* --------------------------------------------
- calculating Fit curve
- -------------------------------------------- */
-
- for(n = 0; n < max; n++) {
- spc[n] = bgrnd + (fit_b * exp(fit_a * tim[n]));
- }
-
-
- /* -------------------------------------------
- now we can go and save the fit spectrum
- ------------------------------------------- */
-
- strcpy(z,comment);
- n=instr("|",comment);
- if(n>0) midstr(z,comment,0,n-1);
- strcat(z," | ExpFit");
- writespec("",spc,err,max,2,z);
- free(uer1); free(uer2); free(usp1); free(usp2);
- free(spc); free(err); free(tim);
- exit(0);
- }
-
- sumspc(spc,a,z)
- float spc[];
- int a,z;
- {
- int i,erg;
-
- erg=0;
- for(i=a;i<z;i++) erg=erg+spc[i];
- return(erg);
- }
-
-
- /* ---------------------------------------------------------
- Fitting background to exponential function.
- This is done, by calculating the chi**2 with
- linear regression for the logarithm of the spectrum.
- We than look for a minimum of chi**2 for different
- backgrounds.
- UP TO NOW, THE ERRORBARS ARE NOT INCLUDED !
- I HAVE FORGOTTEN MY OLD SUPERBASIC SOURCE AT HOME, SORRY.
- --------------------------------------------------------- */
- expbafit(spc,tim,err,a,z)
- float spc[],tim[],err[];
- int a,z;
- {
- int i,n,erg,bamin,bamax,babest,inc,xraster,xdepth;
- float chibest;
-
- xraster = 10;
- xdepth = 5;
- chibest = 1E10;
- bamax = sumspc(spc,z-10,z) / 10 ; /* get maximum background */
- bamin = bamax / 2; /* get minimum background */
- for(i=1;i<xdepth;i++) {
- inc = (bamax - bamin) / xraster;
- if(inc<1) break;
- n = bamin; while(n<=bamax) {
- chisq = linreg(spc,tim,err,n,a,z); /* just calculate chi**2 */
- if(chisq < chibest) {
- chibest = chisq;
- babest = n;
- if(flg_v > 1) {
- printf("new best: background = %d chi**2 = %f\n",babest,chibest);
- }
- }
- n = n + inc;
- }
- bamin = babest - inc;
- bamax = babest + inc;
- }
- return(babest);
- }
-